// --- Array.prototype Cross Browser ---
(function(p) {
  // Array.prototype.lastIndexOf()
  p.lastIndexOf || (p.lastIndexOf = function(needle, fromIndex) {
    var iz = this.length, i = fromIndex;

    i = (i < 0) ? i + iz : iz - 1;
    for (; i > -1; --i) {
      if (i in this && this[i] === needle) {
        return i;
      }
    }
    return -1;
  });

  // Array.prototype.indexOf()
  p.indexOf || (p.indexOf = function(needle, fromIndex) {
    var iz = this.length, i = fromIndex || 0;

    i = (i < 0) ? i + iz : i;
    for (; i < iz; ++i) {
      if (i in this && this[i] === needle) {
        return i;
      }
    }
    return -1;
  });

  // Array.prototype.forEach()
  p.forEach || (p.forEach = function(fn, me) {
    var i = 0, iz = this.length;
    for (; i < iz; ++i) {
      if (i in this) {
        fn.call(me, this[i], i, this);
      }
    }
  });

  // Array.prototype.filter()
  p.filter || (p.filter = function(fn, me) {
    var rv = [], ri = -1, i = 0, iz = this.length, v;
    for (; i < iz; ++i) {
      if (i in this) {
        v = this[i];
        if (fn.call(me, v, i, this)) {
          rv[++ri] = v;
        }
      }
    }
    return rv;
  });

  // Array.prototype.every()
  p.every || (p.every = function(fn, me) {
    var i = 0, iz = this.length;
    for (; i < iz; ++i) {
      if (i in this) {
        if (!fn.call(me, this[i], i, this)) {
          return false;
        }
      }
    }
    return true;
  });

  // Array.prototype.some()
  p.some || (p.some = function(fn, me) {
    var i = 0, iz = this.length;
    for (; i < iz; ++i) {
      if (i in this) {
        if (fn.call(me, this[i], i, this)) {
          return true;
        }
      }
    }
    return false;
  });

  // Array.prototype.map()
  p.map || (p.map = function(fn, me) {
    var rv = Array(this.length), i = 0, iz = this.length;
    for (; i < iz; ++i) {
      if (i in this) {
        rv[i] = fn.call(me, this[i], i, this);
      }
    }
    return rv;
  });

  // Array.prototype.reduce()
  p.reduce || (p.reduce = function(fn, initialValue) {
    var rv, i = 0, iz = this.length, found = 0;

    if (initialValue !== void 0) {
      rv = initialValue;
      ++found;
    }
    for (; i < iz; ++i) {
      if (i in this) {
        if (found) {
          rv = fn(rv, this[i], i, this);
        } else {
          rv = this[i];
          ++found;
        }
      }
    }
    if (!found) { throw TypeError(); }
    return rv;
  });

  // Array.prototype.reduceRight()
  p.reduceRight || (p.reduceRight = function(fn, initialValue) {
    var rv, i = 0, found = 0;

    if (initialValue !== void 0) {
      rv = initialValue;
      ++found;
    }
    for (i = this.length - 1; i >= 0; --i) {
      if (i in this) {
        if (found) {
          rv = fn(rv, this[i], i, this);
        } else {
          rv = this[i];
          ++found;
        }
      }
    }
    if (!found) { throw TypeError(); }
    return rv;
  });
})(Array.prototype);

// --- Math Cross Browser ---
(function(p){
  p.toDegrees || (p.toDegrees = 180 / Math.PI); // to degree. from java.math
  p.toRadians || (p.toRadians = Math.PI / 180); // to radian. from java.math
})(Math);

// --- String.prototype Cross Browser ---
(function(p) {
  // String.prototype.trim()
  p.trim || (p.trim = function() {
    return this.replace(/^[\s]+|[\s]+$/g, "");
  });

  // String.prototype.trimLeft()
  p.trimLeft || (p.trimLeft = function() {
    return this.replace(/^[\s]+/g, "");
  });

  // String.prototype.trimRight()
  p.trimRight || (p.trimRight = function() {
    return this.replace(/[\s]+$/g, "");
  });
})(String.prototype);

!document.uniqueID && !HTMLElement.prototype.outerHTML && (function(p) {
  // HTMLElement.prototype.outerHTML
  p.__defineGetter__("outerHTML", function() {
    var range = document.createRange(),
        div = document.createElement("div");
    range.selectNode(this);
    div.appendChild(range.cloneContents());
    return div.innerHTML;
  });
  p.__defineSetter__("outerHTML", function(html) {
    var range = document.createRange(), cf;
    range.setStartBefore(this);
    cf = range.createContextualFragment(html);
    this.parentNode.replaceChild(cf,this);
  });

  // HTMLElement.prototype.innerText
  p.__defineGetter__("innerText", function() {
    return this.textContent;
  });
  p.__defineSetter__("innerText", function(text) {
    while (this.hasChildNodes()) {
      this.removeChild(this.lastChild);
    }
    this.appendChild(document.createTextNode(text));
  });
})(HTMLElement.prototype);
